"""
机器学习策略模块

基于机器学习算法实现的交易策略，支持分类预测、回归预测、强化学习等方法。
"""

from typing import Dict, List, Any, Optional, Tuple, Union
from datetime import datetime, timedelta
from dataclasses import dataclass, field
from enum import Enum
import pandas as pd
import numpy as np  # type: ignore

from .base_strategy import (
    BaseStrategy, StrategyConfig, StrategyType, RiskLevel,
    Position, Signal, StrategyMetrics, SignalType
)
from ..analysis.factor_analysis import FactorAnalyzer
from ..analysis.market_analysis import MarketAnalyzer


class MLModelType(Enum):
    """机器学习模型类型"""
    LINEAR_REGRESSION = "linear_regression"
    RANDOM_FOREST = "random_forest"
    GRADIENT_BOOSTING = "gradient_boosting"
    SVM = "svm"
    NEURAL_NETWORK = "neural_network"
    LSTM = "lstm"
    TRANSFORMER = "transformer"
    REINFORCEMENT_LEARNING = "reinforcement_learning"


class PredictionType(Enum):
    """预测类型"""
    CLASSIFICATION = "classification"  # 分类预测（涨跌方向）
    REGRESSION = "regression"  # 回归预测（价格/收益率）
    RANKING = "ranking"  # 排序预测（相对强弱）


class FeatureType(Enum):
    """特征类型"""
    TECHNICAL = "technical"  # 技术指标特征
    FUNDAMENTAL = "fundamental"  # 基本面特征
    MARKET = "market"  # 市场特征
    SENTIMENT = "sentiment"  # 情绪特征
    MACRO = "macro"  # 宏观经济特征


@dataclass
class FeatureConfig:
    """特征配置"""
    feature_type: FeatureType
    feature_names: List[str]
    lookback_period: int = 20
    normalization: str = "zscore"  # zscore, minmax, robust
    lag_periods: List[int] = field(default_factory=lambda: [1, 5, 10])
    rolling_windows: List[int] = field(default_factory=lambda: [5, 10, 20])
    
    def __post_init__(self):
        """后初始化验证"""
        if self.lookback_period <= 0:
            raise ValueError("lookback_period必须大于0")
        if not self.feature_names:
            raise ValueError("feature_names不能为空")


@dataclass
class ModelConfig:
    """模型配置"""
    model_type: MLModelType
    prediction_type: PredictionType
    hyperparameters: Dict[str, Any] = field(default_factory=dict)
    training_period: int = 252  # 训练周期（交易日）
    retraining_frequency: int = 20  # 重训练频率（交易日）
    validation_split: float = 0.2
    cross_validation_folds: int = 5
    early_stopping: bool = True
    feature_selection: bool = True
    ensemble_methods: List[str] = field(default_factory=list)
    
    def __post_init__(self):
        """后初始化验证"""
        if self.training_period <= 0:
            raise ValueError("training_period必须大于0")
        if not 0 < self.validation_split < 1:
            raise ValueError("validation_split必须在0和1之间")


@dataclass
class MLStrategyConfig(StrategyConfig):
    """机器学习策略配置"""
    strategy_type: StrategyType = StrategyType.MACHINE_LEARNING
    
    # 模型配置
    model_config: ModelConfig = field(default_factory=lambda: ModelConfig(
        model_type=MLModelType.RANDOM_FOREST,
        prediction_type=PredictionType.CLASSIFICATION
    ))
    
    # 特征配置
    feature_configs: List[FeatureConfig] = field(default_factory=list)
    
    # 预测配置
    prediction_horizon: int = 1  # 预测时间范围（天）
    confidence_threshold: float = 0.6  # 置信度阈值
    prediction_update_frequency: int = 1  # 预测更新频率（天）
    
    # 信号配置
    signal_threshold: float = 0.5  # 信号阈值
    signal_smoothing: bool = True
    signal_confirmation: bool = True
    
    # 风险控制
    max_prediction_uncertainty: float = 0.3
    model_performance_threshold: float = 0.55
    feature_importance_threshold: float = 0.01
    
    def __post_init__(self):
        """后初始化验证"""
        # 移除不存在的super().__post_init__()调用
        pass
        if self.prediction_horizon <= 0:
            raise ValueError("prediction_horizon必须大于0")
        if not 0 <= self.confidence_threshold <= 1:
            raise ValueError("confidence_threshold必须在0和1之间")


class MLStrategy(BaseStrategy):
    """
    机器学习策略
    
    基于机器学习算法进行价格预测和信号生成的交易策略。
    支持多种模型类型和特征工程方法。
    """
    
    def __init__(self, config: MLStrategyConfig):
        """
        初始化机器学习策略
        
        Args:
            config: 策略配置
        """
        super().__init__(config)
        self.config = config
        
        # 添加logger属性
        import logging
        self.logger = logging.getLogger(__name__)
        
        # 模型相关
        self._models: Dict[str, Any] = {}
        self._model_performance: Dict[str, Dict[str, float]] = {}
        self._feature_importance: Dict[str, Dict[str, float]] = {}
        self._last_training_date: Optional[datetime] = None
        
        # 特征相关
        self._features: Dict[str, pd.DataFrame] = {}
        self._feature_scalers: Dict[str, Any] = {}
        self._feature_selectors: Dict[str, Any] = {}
        
        # 预测相关
        self._predictions: Dict[str, Dict[str, float]] = {}
        self._prediction_confidence: Dict[str, Dict[str, float]] = {}
        self._prediction_history: Dict[str, List[Dict[str, Any]]] = {}
        
        # 分析器
        self._factor_analyzer = FactorAnalyzer()
        self._market_analyzer = MarketAnalyzer()
        
        # 初始化组件
        self._initialize_models()
        self._initialize_features()
    
    def _initialize_models(self) -> None:
        """初始化模型"""
        try:
            # 根据模型类型初始化不同的模型
            model_type = self.config.model_config.model_type
            
            if model_type == MLModelType.RANDOM_FOREST:
                self._initialize_random_forest()
            elif model_type == MLModelType.GRADIENT_BOOSTING:
                self._initialize_gradient_boosting()
            elif model_type == MLModelType.NEURAL_NETWORK:
                self._initialize_neural_network()
            elif model_type == MLModelType.LSTM:
                self._initialize_lstm()
            elif model_type == MLModelType.SVM:
                self._initialize_svm()
            elif model_type == MLModelType.LINEAR_REGRESSION:
                self._initialize_linear_regression()
            else:
                raise ValueError(f"不支持的模型类型: {model_type}")
                
        except Exception as e:
            self.logger.error(f"模型初始化失败: {e}")
            raise
    
    def _initialize_random_forest(self) -> None:
        """初始化随机森林模型"""
        try:
            # 这里应该导入sklearn，但为了避免依赖问题，使用模拟实现
            default_params = {
                'n_estimators': 100,
                'max_depth': 10,
                'min_samples_split': 5,
                'min_samples_leaf': 2,
                'random_state': 42
            }
            
            params = {**default_params, **self.config.model_config.hyperparameters}
            
            # 模拟模型对象
            self._models['main'] = {
                'type': 'random_forest',
                'params': params,
                'trained': False
            }
            
        except Exception as e:
            self.logger.error(f"随机森林模型初始化失败: {e}")
            raise
    
    def _initialize_gradient_boosting(self) -> None:
        """初始化梯度提升模型"""
        try:
            default_params = {
                'n_estimators': 100,
                'learning_rate': 0.1,
                'max_depth': 6,
                'subsample': 0.8,
                'random_state': 42
            }
            
            params = {**default_params, **self.config.model_config.hyperparameters}
            
            self._models['main'] = {
                'type': 'gradient_boosting',
                'params': params,
                'trained': False
            }
            
        except Exception as e:
            self.logger.error(f"梯度提升模型初始化失败: {e}")
            raise
    
    def _initialize_neural_network(self) -> None:
        """初始化神经网络模型"""
        try:
            default_params = {
                'hidden_layers': [64, 32, 16],
                'activation': 'relu',
                'dropout_rate': 0.2,
                'learning_rate': 0.001,
                'batch_size': 32,
                'epochs': 100
            }
            
            params = {**default_params, **self.config.model_config.hyperparameters}
            
            self._models['main'] = {
                'type': 'neural_network',
                'params': params,
                'trained': False
            }
            
        except Exception as e:
            self.logger.error(f"神经网络模型初始化失败: {e}")
            raise
    
    def _initialize_lstm(self) -> None:
        """初始化LSTM模型"""
        try:
            default_params = {
                'lstm_units': [50, 50],
                'dropout_rate': 0.2,
                'learning_rate': 0.001,
                'batch_size': 32,
                'epochs': 100,
                'sequence_length': 20
            }
            
            params = {**default_params, **self.config.model_config.hyperparameters}
            
            self._models['main'] = {
                'type': 'lstm',
                'params': params,
                'trained': False
            }
            
        except Exception as e:
            self.logger.error(f"LSTM模型初始化失败: {e}")
            raise
    
    def _initialize_svm(self) -> None:
        """初始化SVM模型"""
        try:
            default_params = {
                'kernel': 'rbf',
                'C': 1.0,
                'gamma': 'scale',
                'probability': True
            }
            
            params = {**default_params, **self.config.model_config.hyperparameters}
            
            self._models['main'] = {
                'type': 'svm',
                'params': params,
                'trained': False
            }
            
        except Exception as e:
            self.logger.error(f"SVM模型初始化失败: {e}")
            raise
    
    def _initialize_linear_regression(self) -> None:
        """初始化线性回归模型"""
        try:
            default_params = {
                'fit_intercept': True,
                'normalize': False,
                'alpha': 1.0  # 正则化参数
            }
            
            params = {**default_params, **self.config.model_config.hyperparameters}
            
            self._models['main'] = {
                'type': 'linear_regression',
                'params': params,
                'trained': False
            }
            
        except Exception as e:
            self.logger.error(f"线性回归模型初始化失败: {e}")
            raise
    
    def _initialize_features(self) -> None:
        """初始化特征工程"""
        try:
            for feature_config in self.config.feature_configs:
                feature_type = feature_config.feature_type.value
                
                # 初始化特征缓存
                self._features[feature_type] = pd.DataFrame()
                
                # 初始化特征缩放器
                self._feature_scalers[feature_type] = {
                    'type': feature_config.normalization,
                    'fitted': False
                }
                
                # 初始化特征选择器
                if self.config.model_config.feature_selection:
                    self._feature_selectors[feature_type] = {
                        'method': 'mutual_info',
                        'fitted': False
                    }
                    
        except Exception as e:
            self.logger.error(f"特征初始化失败: {e}")
            raise
    
    async def generate_signal(
        self,
        symbol: str,
        data: pd.DataFrame,
        current_time: datetime
    ) -> Signal:
        """
        生成交易信号
        
        Args:
            symbol: 交易标的
            data: 市场数据
            current_time: 当前时间
            
        Returns:
            交易信号
        """
        try:
            # 检查数据有效性
            if data.empty or len(data) < self.config.model_config.training_period:
                return Signal(
                    symbol=symbol,
                    signal_type=SignalType.HOLD,
                    strength=0.0,
                    confidence=0.0,
                    timestamp=current_time,
                    metadata={"reason": "数据不足"}
                )
            
            # 检查是否需要重新训练模型
            await self._check_and_retrain_model(symbol, data, current_time)
            
            # 生成特征
            features = await self._generate_features(symbol, data, current_time)
            
            if features.empty:
                return Signal(
                    symbol=symbol,
                    signal_type=SignalType.HOLD,
                    strength=0.0,
                    confidence=0.0,
                    timestamp=current_time,
                    metadata={"reason": "特征生成失败"}
                )
            
            # 进行预测
            prediction, confidence = await self._make_prediction(
                symbol, features, current_time
            )
            
            # 生成信号
            signal = await self._generate_signal_from_prediction(
                symbol, prediction, confidence, current_time
            )
            
            # 记录预测历史
            self._record_prediction(symbol, prediction, confidence, current_time)
            
            return signal
            
        except Exception as e:
            self.logger.error(f"信号生成失败 {symbol}: {e}")
            return Signal(
                symbol=symbol,
                signal_type=SignalType.HOLD,
                strength=0.0,
                confidence=0.0,
                timestamp=current_time,
                metadata={"error": str(e)}
            )
    
    async def _check_and_retrain_model(
        self,
        symbol: str,
        data: pd.DataFrame,
        current_time: datetime
    ) -> None:
        """检查并重新训练模型"""
        try:
            # 检查是否需要重新训练
            need_retrain = False
            
            # 首次训练
            if not self._models.get('main', {}).get('trained', False):
                need_retrain = True
                
            # 定期重训练
            elif self._last_training_date:
                days_since_training = (current_time - self._last_training_date).days
                if days_since_training >= self.config.model_config.retraining_frequency:
                    need_retrain = True
            
            # 模型性能下降
            if symbol in self._model_performance:
                performance = self._model_performance[symbol]
                if performance.get('accuracy', 0) < self.config.model_performance_threshold:
                    need_retrain = True
            
            if need_retrain:
                await self._train_model(symbol, data, current_time)
                
        except Exception as e:
            self.logger.error(f"模型检查和重训练失败 {symbol}: {e}")
            raise
    
    async def _train_model(
        self,
        symbol: str,
        data: pd.DataFrame,
        current_time: datetime
    ) -> None:
        """训练模型"""
        try:
            self.logger.info(f"开始训练模型 {symbol}")
            
            # 准备训练数据
            train_data = await self._prepare_training_data(symbol, data, current_time)
            
            if train_data is None or train_data[0].empty:
                self.logger.warning(f"训练数据不足 {symbol}")
                return
            
            X_train, y_train = train_data
            
            # 特征选择
            if self.config.model_config.feature_selection:
                X_train = await self._select_features(symbol, X_train, y_train)
            
            # 交叉验证
            if self.config.model_config.cross_validation_folds > 1:
                cv_scores = await self._cross_validate(symbol, X_train, y_train)
                self.logger.info(f"交叉验证得分 {symbol}: {cv_scores}")
            
            # 训练主模型
            await self._fit_model(symbol, X_train, y_train)
            
            # 评估模型性能
            performance = await self._evaluate_model(symbol, X_train, y_train)
            self._model_performance[symbol] = performance
            
            # 更新训练时间
            self._last_training_date = current_time
            self._models['main']['trained'] = True
            
            self.logger.info(f"模型训练完成 {symbol}, 性能: {performance}")
            
        except Exception as e:
            self.logger.error(f"模型训练失败 {symbol}: {e}")
            raise
    
    async def _prepare_training_data(
        self,
        symbol: str,
        data: pd.DataFrame,
        current_time: datetime
    ) -> Optional[Tuple[pd.DataFrame, pd.Series]]:
        """准备训练数据"""
        try:
            # 生成特征
            features = await self._generate_features(symbol, data, current_time)
            
            if features.empty:
                return None
            
            # 生成标签
            labels = await self._generate_labels(symbol, data, current_time)
            
            if labels.empty:
                return None
            
            # 对齐特征和标签
            common_index = features.index.intersection(labels.index)
            
            if len(common_index) < self.config.model_config.training_period:
                return None
            
            X = features.loc[common_index]
            y = labels.loc[common_index]
            
            # 移除缺失值
            mask = ~(X.isnull().any(axis=1) | y.isnull())  # type: ignore
            X_clean = X[mask]
            y_clean = y[mask]
            
            return X_clean, y_clean  # type: ignore
            
        except Exception as e:
            self.logger.error(f"训练数据准备失败 {symbol}: {e}")
            return None
    
    async def _generate_features(
        self,
        symbol: str,
        data: pd.DataFrame,
        current_time: datetime
    ) -> pd.DataFrame:
        """生成特征"""
        try:
            all_features = []
            
            for feature_config in self.config.feature_configs:
                features = await self._generate_feature_type(
                    symbol, data, feature_config, current_time
                )
                
                if not features.empty:
                    all_features.append(features)
            
            if not all_features:
                return pd.DataFrame()
            
            # 合并所有特征
            combined_features = pd.concat(all_features, axis=1)
            
            # 特征缩放
            scaled_features = await self._scale_features(symbol, combined_features)
            
            return scaled_features
            
        except Exception as e:
            self.logger.error(f"特征生成失败 {symbol}: {e}")
            return pd.DataFrame()
    
    async def _generate_feature_type(
        self,
        symbol: str,
        data: pd.DataFrame,
        feature_config: FeatureConfig,
        current_time: datetime
    ) -> pd.DataFrame:
        """生成特定类型的特征"""
        try:
            feature_type = feature_config.feature_type
            
            if feature_type == FeatureType.TECHNICAL:
                return await self._generate_technical_features(
                    symbol, data, feature_config
                )
            elif feature_type == FeatureType.FUNDAMENTAL:
                return await self._generate_fundamental_features(
                    symbol, data, feature_config
                )
            elif feature_type == FeatureType.MARKET:
                return await self._generate_market_features(
                    symbol, data, feature_config
                )
            elif feature_type == FeatureType.SENTIMENT:
                return await self._generate_sentiment_features(
                    symbol, data, feature_config
                )
            elif feature_type == FeatureType.MACRO:
                return await self._generate_macro_features(
                    symbol, data, feature_config
                )
            else:
                return pd.DataFrame()
                
        except Exception as e:
            feature_type = getattr(feature_config, 'feature_type', 'unknown')
            self.logger.error(f"特征类型生成失败 {symbol} {feature_type}: {e}")
            return pd.DataFrame()
    
    async def _generate_technical_features(
        self,
        symbol: str,
        data: pd.DataFrame,
        feature_config: FeatureConfig
    ) -> pd.DataFrame:
        """生成技术指标特征"""
        try:
            features = pd.DataFrame(index=data.index)
            
            # 价格特征
            if 'price' in feature_config.feature_names:
                features['close'] = data['close']
                features['high'] = data['high']
                features['low'] = data['low']
                features['open'] = data['open']
            
            # 收益率特征
            if 'returns' in feature_config.feature_names:
                features['returns'] = data['close'].pct_change()
                
                # 滞后收益率
                for lag in feature_config.lag_periods:
                    features[f'returns_lag_{lag}'] = features['returns'].shift(lag)
            
            # 移动平均特征
            if 'moving_average' in feature_config.feature_names:
                for window in feature_config.rolling_windows:
                    features[f'sma_{window}'] = data['close'].rolling(window).mean()
                    features[f'ema_{window}'] = data['close'].ewm(span=window).mean()
            
            # 波动率特征
            if 'volatility' in feature_config.feature_names:
                for window in feature_config.rolling_windows:
                    features[f'volatility_{window}'] = (
                        features['returns'].rolling(window).std()
                    )
            
            # 成交量特征
            if 'volume' in feature_config.feature_names and 'volume' in data.columns:
                features['volume'] = data['volume']
                features['volume_sma'] = data['volume'].rolling(20).mean()
                features['volume_ratio'] = data['volume'] / features['volume_sma']
            
            return features.dropna()
            
        except Exception as e:
            self.logger.error(f"技术特征生成失败 {symbol}: {e}")
            return pd.DataFrame()
    
    async def _generate_fundamental_features(
        self,
        symbol: str,
        data: pd.DataFrame,
        feature_config: FeatureConfig
    ) -> pd.DataFrame:
        """生成基本面特征"""
        try:
            # 这里应该从基本面数据源获取数据
            # 暂时返回空DataFrame
            return pd.DataFrame()
            
        except Exception as e:
            self.logger.error(f"基本面特征生成失败 {symbol}: {e}")
            return pd.DataFrame()
    
    async def _generate_market_features(
        self,
        symbol: str,
        data: pd.DataFrame,
        feature_config: FeatureConfig
    ) -> pd.DataFrame:
        """生成市场特征"""
        try:
            features = pd.DataFrame(index=data.index)
            
            # 市场相对表现
            if 'relative_performance' in feature_config.feature_names:
                # 这里应该计算相对于市场指数的表现
                # 暂时使用模拟数据
                features['relative_performance'] = np.random.randn(len(data))
            
            return features.dropna()
            
        except Exception as e:
            self.logger.error(f"市场特征生成失败 {symbol}: {e}")
            return pd.DataFrame()
    
    async def _generate_sentiment_features(
        self,
        symbol: str,
        data: pd.DataFrame,
        feature_config: FeatureConfig
    ) -> pd.DataFrame:
        """生成情绪特征"""
        try:
            # 这里应该从情绪数据源获取数据
            # 暂时返回空DataFrame
            return pd.DataFrame()
            
        except Exception as e:
            self.logger.error(f"情绪特征生成失败 {symbol}: {e}")
            return pd.DataFrame()
    
    async def _generate_macro_features(
        self,
        symbol: str,
        data: pd.DataFrame,
        feature_config: FeatureConfig
    ) -> pd.DataFrame:
        """生成宏观经济特征"""
        try:
            # 这里应该从宏观经济数据源获取数据
            # 暂时返回空DataFrame
            return pd.DataFrame()
            
        except Exception as e:
            self.logger.error(f"宏观特征生成失败 {symbol}: {e}")
            return pd.DataFrame()
    
    async def _generate_labels(
        self,
        symbol: str,
        data: pd.DataFrame,
        current_time: datetime
    ) -> pd.Series:
        """生成标签"""
        try:
            prediction_type = self.config.model_config.prediction_type
            horizon = self.config.prediction_horizon
            
            if prediction_type == PredictionType.CLASSIFICATION:
                # 分类标签：未来收益率的方向
                future_returns = data['close'].pct_change(horizon).shift(-horizon)
                labels = (future_returns > 0).astype(int)
                
            elif prediction_type == PredictionType.REGRESSION:
                # 回归标签：未来收益率
                labels = data['close'].pct_change(horizon).shift(-horizon)
                
            elif prediction_type == PredictionType.RANKING:
                # 排序标签：相对排名
                future_returns = data['close'].pct_change(horizon).shift(-horizon)
                labels = future_returns.rank(pct=True)
                
            else:
                raise ValueError(f"不支持的预测类型: {prediction_type}")
            
            return labels.dropna()
            
        except Exception as e:
            self.logger.error(f"标签生成失败 {symbol}: {e}")
            return pd.Series()
    
    async def _scale_features(
        self,
        symbol: str,
        features: pd.DataFrame
    ) -> pd.DataFrame:
        """特征缩放"""
        try:
            scaled_features = features.copy()
            
            for feature_type, scaler_config in self._feature_scalers.items():
                if scaler_config['type'] == 'zscore':
                    # Z-score标准化
                    if not scaler_config['fitted']:
                        # 计算均值和标准差
                        scaler_config['mean'] = features.mean()
                        scaler_config['std'] = features.std()
                        scaler_config['fitted'] = True
                    
                    scaled_features = (
                        (features - scaler_config['mean']) / scaler_config['std']
                    )
                    
                elif scaler_config['type'] == 'minmax':
                    # Min-Max标准化
                    if not scaler_config['fitted']:
                        scaler_config['min'] = features.min()
                        scaler_config['max'] = features.max()
                        scaler_config['fitted'] = True
                    
                    scaled_features = (
                        (features - scaler_config['min']) / 
                        (scaler_config['max'] - scaler_config['min'])
                    )
            
            return scaled_features.fillna(0)
            
        except Exception as e:
            self.logger.error(f"特征缩放失败 {symbol}: {e}")
            return features
    
    async def _select_features(
        self,
        symbol: str,
        X: pd.DataFrame,
        y: pd.Series
    ) -> pd.DataFrame:
        """特征选择"""
        try:
            # 简单的特征选择：基于相关性
            correlations = X.corrwith(y).abs()
            selected_features = correlations[
                correlations > self.config.feature_importance_threshold
            ].index
            
            return X[selected_features].copy()  # type: ignore
            
        except Exception as e:
            self.logger.error(f"特征选择失败 {symbol}: {e}")
            return X
    
    async def _cross_validate(
        self,
        symbol: str,
        X: pd.DataFrame,
        y: pd.Series
    ) -> Dict[str, float]:
        """交叉验证"""
        try:
            # 简化的交叉验证实现
            n_folds = self.config.model_config.cross_validation_folds
            fold_size = len(X) // n_folds
            
            scores = []
            
            for i in range(n_folds):
                start_idx = i * fold_size
                end_idx = (i + 1) * fold_size if i < n_folds - 1 else len(X)
                
                # 验证集
                X_val = X.iloc[start_idx:end_idx]
                y_val = y.iloc[start_idx:end_idx]
                
                # 训练集
                X_train_cv = pd.concat([X.iloc[:start_idx], X.iloc[end_idx:]])
                y_train_cv = pd.concat([y.iloc[:start_idx], y.iloc[end_idx:]])
                
                # 模拟训练和评估
                # 这里应该实际训练模型并评估
                score = np.random.uniform(0.5, 0.8)  # 模拟得分
                scores.append(score)
            
            return {
                'mean_score': np.mean(scores),
                'std_score': np.std(scores),
                'scores': float(np.mean(scores))
            }
            
        except Exception as e:
            self.logger.error(f"交叉验证失败 {symbol}: {e}")
            return {'mean_score': 0.5, 'std_score': 0.0, 'scores': 0.0}
    
    async def _fit_model(
        self,
        symbol: str,
        X: pd.DataFrame,
        y: pd.Series
    ) -> None:
        """训练模型"""
        try:
            # 模拟模型训练
            model = self._models['main']
            model['trained'] = True
            model['training_data_shape'] = X.shape
            model['training_time'] = datetime.now()
            
            self.logger.info(f"模型训练完成 {symbol}: {X.shape}")
            
        except Exception as e:
            self.logger.error(f"模型训练失败 {symbol}: {e}")
            raise
    
    async def _evaluate_model(
        self,
        symbol: str,
        X: pd.DataFrame,
        y: pd.Series
    ) -> Dict[str, float]:
        """评估模型性能"""
        try:
            # 模拟模型评估
            performance = {
                'accuracy': np.random.uniform(0.55, 0.75),
                'precision': np.random.uniform(0.5, 0.7),
                'recall': np.random.uniform(0.5, 0.7),
                'f1_score': np.random.uniform(0.5, 0.7),
                'auc': np.random.uniform(0.55, 0.8)
            }
            
            return performance
            
        except Exception as e:
            self.logger.error(f"模型评估失败 {symbol}: {e}")
            return {'accuracy': 0.5}
    
    async def _make_prediction(
        self,
        symbol: str,
        features: pd.DataFrame,
        current_time: datetime
    ) -> Tuple[float, float]:
        """进行预测"""
        try:
            # 检查模型是否已训练
            if not self._models.get('main', {}).get('trained', False):
                return 0.0, 0.0
            
            # 模拟预测
            prediction = np.random.uniform(-0.1, 0.1)  # 模拟预测值
            confidence = np.random.uniform(0.5, 0.9)   # 模拟置信度
            
            return prediction, confidence
            
        except Exception as e:
            self.logger.error(f"预测失败 {symbol}: {e}")
            return 0.0, 0.0
    
    async def _generate_signal_from_prediction(
        self,
        symbol: str,
        prediction: float,
        confidence: float,
        current_time: datetime
    ) -> Signal:
        """从预测生成信号"""
        try:
            # 检查置信度阈值
            if confidence < self.config.confidence_threshold:
                return Signal(
                    symbol=symbol,
                    signal_type=SignalType.HOLD,
                    strength=0.0,
                    confidence=confidence,
                    timestamp=current_time,
                    metadata={"reason": "置信度不足"}
                )
            
            # 根据预测类型生成信号
            prediction_type = self.config.model_config.prediction_type
            
            if prediction_type == PredictionType.CLASSIFICATION:
                # 分类预测：0表示下跌，1表示上涨
                if prediction > 0.5:
                    signal_type = SignalType.BUY
                    strength = (prediction - 0.5) * 2  # 转换为0-1范围
                elif prediction < 0.5:
                    signal_type = SignalType.SELL
                    strength = (0.5 - prediction) * 2
                else:
                    signal_type = SignalType.HOLD
                    strength = 0.0
                    
            elif prediction_type == PredictionType.REGRESSION:
                # 回归预测：预测收益率
                if prediction > self.config.signal_threshold:
                    signal_type = SignalType.BUY
                    strength = min(abs(prediction) * 10, 1.0)  # 缩放强度
                elif prediction < -self.config.signal_threshold:
                    signal_type = SignalType.SELL
                    strength = min(abs(prediction) * 10, 1.0)
                else:
                    signal_type = SignalType.HOLD
                    strength = 0.0
                    
            else:  # RANKING
                # 排序预测：相对排名
                if prediction > 0.7:
                    signal_type = SignalType.BUY
                    strength = (prediction - 0.5) * 2
                elif prediction < 0.3:
                    signal_type = SignalType.SELL
                    strength = (0.5 - prediction) * 2
                else:
                    signal_type = SignalType.HOLD
                    strength = 0.0
            
            return Signal(
                symbol=symbol,
                signal_type=signal_type,
                strength=strength,
                confidence=confidence,
                timestamp=current_time,
                metadata={
                    "prediction": prediction,
                    "prediction_type": prediction_type.value,
                    "model_type": self.config.model_config.model_type.value
                }
            )
            
        except Exception as e:
            self.logger.error(f"信号生成失败 {symbol}: {e}")
            return Signal(
                symbol=symbol,
                signal_type=SignalType.HOLD,
                strength=0.0,
                confidence=0.0,
                timestamp=current_time,
                metadata={"error": str(e)}
            )
    
    def _record_prediction(
        self,
        symbol: str,
        prediction: float,
        confidence: float,
        current_time: datetime
    ) -> None:
        """记录预测历史"""
        try:
            if symbol not in self._prediction_history:
                self._prediction_history[symbol] = []
            
            record = {
                'timestamp': current_time,
                'prediction': prediction,
                'confidence': confidence,
                'model_type': self.config.model_config.model_type.value
            }
            
            self._prediction_history[symbol].append(record)
            
            # 保持历史记录数量限制
            max_history = 1000
            if len(self._prediction_history[symbol]) > max_history:
                self._prediction_history[symbol] = self._prediction_history[symbol][-max_history:]
                
        except Exception as e:
            self.logger.error(f"预测记录失败 {symbol}: {e}")
    
    async def update_position(
        self,
        symbol: str,
        current_position: Position,
        signal: Signal,
        current_time: datetime
    ) -> Position:
        """
        更新持仓
        
        Args:
            symbol: 交易标的
            current_position: 当前持仓
            signal: 交易信号
            current_time: 当前时间
            
        Returns:
            更新后的持仓
        """
        try:
            # 基于信号强度和置信度调整持仓
            if signal.signal_type == SignalType.BUY and signal.confidence > self.config.confidence_threshold:
                target_size = signal.strength * self.config.max_position_size
                
            elif signal.signal_type == SignalType.SELL and signal.confidence > self.config.confidence_threshold:
                target_size = -signal.strength * self.config.max_position_size
                
            else:
                target_size = 0.0
            
            # 应用风险控制
            target_size = self._apply_risk_controls(symbol, target_size, current_time)
            
            # 更新持仓
            # 获取当前价格（这里需要从参数传入或其他方式获取）
            current_price = 100.0  # 临时使用固定价格，实际应该从数据源获取
            
            new_position = Position(
                symbol=symbol,
                quantity=target_size,
                avg_price=current_price,
                current_price=current_price,
                market_value=target_size * current_price,
                unrealized_pnl=0.0,
                realized_pnl=0.0,
                entry_time=current_time,
                last_update=current_time
            )
            
            return new_position
            
        except Exception as e:
            self.logger.error(f"持仓更新失败 {symbol}: {e}")
            return current_position
    
    def _apply_risk_controls(
        self,
        symbol: str,
        target_size: float,
        current_time: datetime
    ) -> float:
        """应用风险控制"""
        try:
            # 检查模型性能
            if symbol in self._model_performance:
                performance = self._model_performance[symbol]
                if performance.get('accuracy', 0) < self.config.model_performance_threshold:
                    target_size *= 0.5  # 降低仓位
            
            # 检查预测不确定性
            if symbol in self._prediction_confidence:
                avg_confidence = np.mean(list(self._prediction_confidence[symbol].values()))
                if avg_confidence < self.config.confidence_threshold:
                    target_size *= 0.7  # 降低仓位
            
            # 应用最大仓位限制
            target_size = max(-self.config.max_position_size,
                            min(self.config.max_position_size, target_size))
            
            return target_size
            
        except Exception as e:
            self.logger.error(f"风险控制应用失败 {symbol}: {e}")
            return target_size
    
    def _safe_get_datetime(self, timestamp) -> datetime:
        """安全地将时间戳转换为datetime对象"""
        if timestamp is None:
            return datetime.now()
        
        try:
            if isinstance(timestamp, datetime):
                return timestamp
            elif hasattr(timestamp, 'to_pydatetime'):
                return timestamp.to_pydatetime()
            elif hasattr(timestamp, 'to_datetime'):
                return timestamp.to_datetime()
            else:
                return datetime.now()
        except (TypeError, ValueError, AttributeError):
            return datetime.now()
    
    async def calculate_metrics(
        self,
        returns: pd.Series,
        benchmark_returns: Optional[pd.Series] = None
    ) -> StrategyMetrics:
        """
        计算策略指标
        
        Args:
            returns: 策略收益率序列
            benchmark_returns: 基准收益率序列
            
        Returns:
            策略指标
        """
        try:
            if returns.empty:
                return StrategyMetrics(
                    total_return=0.0,
                    annual_return=0.0,
                    volatility=0.0,
                    sharpe_ratio=0.0,
                    max_drawdown=0.0,
                    win_rate=0.0,
                    profit_loss_ratio=0.0,
                    total_trades=0,
                    profitable_trades=0,
                    losing_trades=0,
                    avg_trade_return=0.0,
                    avg_holding_period=0.0,
                    turnover_rate=0.0,
                    information_ratio=0.0,
                    calmar_ratio=0.0,
                    sortino_ratio=0.0,
                    var_95=0.0,
                    cvar_95=0.0,
                    beta=0.0,
                    alpha=0.0,
                    tracking_error=0.0,
                    start_date=datetime.now(),
                    end_date=datetime.now(),
                    last_update=datetime.now()
                )
            
            # 计算基础指标
            # 计算总收益率，确保类型安全
            try:
                prod_result = (1 + returns).prod()
                if pd.isna(prod_result) or not isinstance(prod_result, (int, float)):
                    total_return = 0.0
                else:
                    total_return = float(prod_result) - 1.0
            except (TypeError, ValueError, AttributeError):
                total_return = 0.0
            annual_return = (1 + returns.mean()) ** 252 - 1
            volatility = returns.std() * np.sqrt(252)
            sharpe_ratio = annual_return / volatility if volatility > 0 else 0.0
            
            # 计算最大回撤
            cumulative_returns = (1 + returns).cumprod()
            running_max = cumulative_returns.expanding().max()
            drawdowns = (cumulative_returns - running_max) / running_max
            # 计算最大回撤，确保类型安全
            try:
                min_drawdown = drawdowns.min()
                if pd.isna(min_drawdown) or not isinstance(min_drawdown, (int, float)):
                    max_drawdown = 0.0
                else:
                    max_drawdown = float(abs(min_drawdown))
            except (TypeError, ValueError, AttributeError):
                max_drawdown = 0.0
            
            # 计算胜率
            winning_trades = len(returns[returns > 0])
            losing_trades = len(returns[returns < 0])
            total_trades = len(returns)
            win_rate = winning_trades / total_trades if total_trades > 0 else 0.0
            
            # 计算盈亏比
            avg_win = returns[returns > 0].mean() if winning_trades > 0 else 0.0
            avg_loss = abs(returns[returns < 0].mean()) if losing_trades > 0 else 0.0
            profit_loss_ratio = avg_win / avg_loss if avg_loss > 0 else 0.0
            
            # 其他指标
            avg_trade_return = returns.mean()
            sortino_ratio = annual_return / (returns[returns < 0].std() * np.sqrt(252)) if len(returns[returns < 0]) > 0 else 0.0
            var_95 = returns.quantile(0.05)
            cvar_95 = returns[returns <= var_95].mean()
            
            # 基准相关指标
            beta = 0.0
            alpha = 0.0
            information_ratio = 0.0
            tracking_error = 0.0
            
            if benchmark_returns is not None and not benchmark_returns.empty:
                # 对齐数据
                aligned_returns = returns.reindex(benchmark_returns.index).dropna()
                aligned_benchmark = benchmark_returns.reindex(returns.index).dropna()
                
                if len(aligned_returns) > 1 and len(aligned_benchmark) > 1:
                    covariance = np.cov(aligned_returns, aligned_benchmark)[0, 1]
                    benchmark_variance = np.var(aligned_benchmark)
                    beta = covariance / benchmark_variance if benchmark_variance > 0 else 0.0
                    
                    benchmark_annual_return = (1 + aligned_benchmark.mean()) ** 252 - 1
                    alpha = annual_return - beta * benchmark_annual_return
                    
                    excess_returns = aligned_returns - aligned_benchmark
                    tracking_error = excess_returns.std() * np.sqrt(252)
                    try:
                        excess_mean = excess_returns.mean()
                        if pd.isna(excess_mean) or not isinstance(excess_mean, (int, float)):
                            information_ratio = 0.0
                        else:
                            information_ratio = float(excess_mean) * 252 / tracking_error if tracking_error > 0 else 0.0
                    except (TypeError, ValueError, AttributeError):
                        information_ratio = 0.0
            
            return StrategyMetrics(
                total_return=total_return,
                annual_return=annual_return,
                volatility=volatility,
                sharpe_ratio=sharpe_ratio,
                max_drawdown=max_drawdown,
                win_rate=win_rate,
                profit_loss_ratio=profit_loss_ratio,
                total_trades=total_trades,
                profitable_trades=winning_trades,
                losing_trades=losing_trades,
                avg_trade_return=avg_trade_return,
                avg_holding_period=1.0,  # 简化处理
                turnover_rate=0.0,  # 简化处理
                information_ratio=information_ratio,
                calmar_ratio=annual_return / max_drawdown if max_drawdown > 0 else 0.0,
                sortino_ratio=sortino_ratio,
                var_95=var_95,
                cvar_95=cvar_95,
                beta=beta,
                alpha=alpha,
                tracking_error=tracking_error,
                start_date=self._safe_get_datetime(returns.index[0] if len(returns) > 0 else None),
                end_date=self._safe_get_datetime(returns.index[-1] if len(returns) > 0 else None),
                last_update=datetime.now()
            )
            
        except Exception as e:
            self.logger.error(f"指标计算失败: {e}")
            return StrategyMetrics(
                total_return=0.0,
                annual_return=0.0,
                volatility=0.0,
                sharpe_ratio=0.0,
                max_drawdown=0.0,
                win_rate=0.0,
                profit_loss_ratio=0.0,
                total_trades=0,
                profitable_trades=0,
                losing_trades=0,
                avg_trade_return=0.0,
                avg_holding_period=0.0,
                turnover_rate=0.0,
                information_ratio=0.0,
                calmar_ratio=0.0,
                sortino_ratio=0.0,
                var_95=0.0,
                cvar_95=0.0,
                beta=0.0,
                alpha=0.0,
                tracking_error=0.0,
                start_date=datetime.now(),
                end_date=datetime.now(),
                last_update=datetime.now()
            )
    
    async def _calculate_ml_metrics(
        self,
        symbol: str,
        current_time: datetime
    ) -> Dict[str, Any]:
        """计算机器学习特定指标"""
        try:
            metrics = {}
            
            # 模型性能指标
            if symbol in self._model_performance:
                performance = self._model_performance[symbol]
                metrics.update({
                    'model_accuracy': performance.get('accuracy', 0.0),
                    'model_precision': performance.get('precision', 0.0),
                    'model_recall': performance.get('recall', 0.0),
                    'model_f1_score': performance.get('f1_score', 0.0)
                })
            
            # 预测置信度指标
            if symbol in self._prediction_confidence:
                confidences = list(self._prediction_confidence[symbol].values())
                if confidences:
                    metrics.update({
                        'avg_prediction_confidence': np.mean(confidences),
                        'min_prediction_confidence': np.min(confidences),
                        'max_prediction_confidence': np.max(confidences)
                    })
            
            # 特征重要性指标
            if symbol in self._feature_importance:
                importance = self._feature_importance[symbol]
                if importance:
                    metrics.update({
                        'top_feature': max(importance.keys(), key=lambda k: importance[k]) if importance else '',
                        'feature_diversity': len([v for v in importance.values() if v > 0.01])
                    })
            
            return metrics
            
        except Exception as e:
            self.logger.error(f"ML指标计算失败 {symbol}: {e}")
            return {}
    
    async def cleanup(self) -> None:
        """清理资源"""
        try:
            # 清理模型
            self._models.clear()
            
            # 清理缓存
            self._features.clear()
            self._predictions.clear()
            self._prediction_confidence.clear()
            
            # 限制历史记录大小
            for symbol in self._prediction_history:
                if len(self._prediction_history[symbol]) > 100:
                    self._prediction_history[symbol] = self._prediction_history[symbol][-100:]
            
            self.logger.info("ML策略资源清理完成")
            
        except Exception as e:
            self.logger.error(f"资源清理失败: {e}")